package com.java.IO.zip_stream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipOutputStreamAPI {
    // 压缩文件或文件夹
    public static void zipFileOrDir(String unZipPath, String zipPath, String encode) throws Exception {
        File unZipFile = new File(unZipPath);
        if (!unZipFile.exists()) {
            throw new Exception("路径错误，请检查路径是否存在。错误路径为" + unZipFile.getPath());
        }
        
        File zipRootFile = new File(zipPath);
        if (!zipRootFile.exists() || !zipRootFile.isDirectory()) {
            throw new Exception("路径错误，请检查路径是否存在或正确。错误路径为" + zipRootFile.getPath());
        }
        
        String zipName = unZipFile.getName();
        if (zipName.contains(".")) {
            zipName = zipName.substring(0, zipName.indexOf('.'));
        }
        zipName = zipName + ".zip";
        File zipFile = new File(zipPath, zipName);
        
        try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile), Charset.forName(encode))) {
            zipRecursion(unZipFile, unZipFile.getName(), zipOutputStream);
        }
    }
    
    public static void zipRecursion(File unZipFile, String zipName, ZipOutputStream zipOutputStream) throws IOException {
        if (unZipFile.isFile()) {
            ZipEntry nextEntry = new ZipEntry(zipName);
            zipOutputStream.putNextEntry(nextEntry);
            
            FileInputStream fileInputStream = new FileInputStream(unZipFile);
            int length;
            byte[] buffer = new byte[1024];
            while ((length = fileInputStream.read(buffer)) != -1) {
                zipOutputStream.write(buffer, 0, length);
            }
            return;
        }
        
        File[] listFiles = unZipFile.listFiles();
        for (File listFile : listFiles) {
            zipRecursion(listFile, zipName + File.separator + listFile.getName(), zipOutputStream);
        }
    }
    
    public static void main(String[] args) throws Exception {
        String zipPath = "File和IO流\\com\\java\\files\\zip\\zip";
        
        // 创建对象：创建规则主要依赖于构造形参OutputStream的子类。参数2为字符集，默认UTF-8。注意同一压缩文件的压缩流只能有一个
        ZipOutputStream zipOutputStream1 = new ZipOutputStream(new FileOutputStream(zipPath + "\\students.zip"));
        // ZipOutputStream zipOutputStream2 = new ZipOutputStream(new FileOutputStream(zipPath + "\\students.zip"), Charset.forName("UTF-8"));
        
        // putNextEntry：向压缩包内放ZipEntry对象
        zipOutputStream1.putNextEntry(new ZipEntry("students.txt"));
        
        // write：写出数据到压缩文件，若参数为整数则会转为ASCII对应的字符
        zipOutputStream1.write(97); // a
        zipOutputStream1.write('9'); // 9
        zipOutputStream1.write('中'); // -
        zipOutputStream1.write("\r\n".getBytes()); // 换行(Windows\r\n、Linux\n、Mac\r)
        zipOutputStream1.write(new byte[]{97, 98, 99, 100}); // abcd
        zipOutputStream1.write(new byte[]{97, 98, 99, 100, 101, 102, 103}, 3, 2); // de
        
        // close：关闭流并释放资源
        zipOutputStream1.close();
        
        // 压缩
        String unZipPathOne = "File和IO流\\com\\java\\files\\zip\\unzip\\students.txt";
        String unZipPathMany = "File和IO流\\com\\java\\files\\zip\\unzip";
        zipFileOrDir(unZipPathOne, zipPath, "UTF-8");
        zipFileOrDir(unZipPathMany, zipPath, "UTF-8");
    }
}
